package backend

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"sync"
	"time"
)

// Logger 自定义日志器
type Logger struct {
	infoLogger    *log.Logger
	warningLogger *log.Logger
	errorLogger   *log.Logger
	debugLogger   *log.Logger
	
	logDir        string
	logFile       *os.File
	mu            sync.Mutex
	maxSize       int64  // 最大文件大小 (MB)
	currentSize   int64  // 当前文件大小
}

// NewLogger 创建新的日志器
func NewLogger(logDir string) (*Logger, error) {
	// 确保日志目录存在
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return nil, fmt.Errorf("failed to create log directory: %v", err)
	}
	
	logger := &Logger{
		logDir:  logDir,
		maxSize: 100, // 默认100MB
	}
	
	// 创建日志文件
	if err := logger.createLogFile(); err != nil {
		return nil, err
	}
	
	// 初始化各个级别的日志器
	logger.infoLogger = log.New(logger, "[INFO] ", log.Ldate|log.Ltime|log.Lmicroseconds)
	logger.warningLogger = log.New(logger, "[WARN] ", log.Ldate|log.Ltime|log.Lmicroseconds)
	logger.errorLogger = log.New(logger, "[ERROR] ", log.Ldate|log.Ltime|log.Lmicroseconds)
	logger.debugLogger = log.New(logger, "[DEBUG] ", log.Ldate|log.Ltime|log.Lmicroseconds)
	
	return logger, nil
}

// createLogFile 创建新的日志文件
func (l *Logger) createLogFile() error {
	l.mu.Lock()
	defer l.mu.Unlock()
	
	// 如果已有文件，先关闭
	if l.logFile != nil {
		l.logFile.Close()
	}
	
	// 生成文件名 (按日期和时间)
	timestamp := time.Now().Format("20060102_150405")
	logFile := filepath.Join(l.logDir, fmt.Sprintf("app_%s.log", timestamp))
	
	// 创建或打开文件
	file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return fmt.Errorf("failed to create log file: %v", err)
	}
	
	// 获取文件信息
	info, err := file.Stat()
	if err != nil {
		file.Close()
		return fmt.Errorf("failed to stat log file: %v", err)
	}
	
	l.logFile = file
	l.currentSize = info.Size()
	
	return nil
}

// Write 实现io.Writer接口
func (l *Logger) Write(p []byte) (n int, err error) {
	l.mu.Lock()
	defer l.mu.Unlock()
	
	// 检查是否需要轮转日志
	if l.currentSize+int64(len(p)) > l.maxSize*1024*1024 {
		if err := l.createLogFile(); err != nil {
			return 0, err
		}
	}
	
	// 写入日志
	n, err = l.logFile.Write(p)
	if err != nil {
		return n, err
	}
	
	l.currentSize += int64(n)
	return n, nil
}

// Info 记录信息日志
func (l *Logger) Info(format string, v ...interface{}) {
	l.infoLogger.Printf(format, v...)
}

// Warning 记录警告日志
func (l *Logger) Warning(format string, v ...interface{}) {
	l.warningLogger.Printf(format, v...)
}

// Error 记录错误日志
func (l *Logger) Error(format string, v ...interface{}) {
	l.errorLogger.Printf(format, v...)
}

// Debug 记录调试日志
func (l *Logger) Debug(format string, v ...interface{}) {
	l.debugLogger.Printf(format, v...)
}

// Close 关闭日志器
func (l *Logger) Close() error {
	l.mu.Lock()
	defer l.mu.Unlock()
	
	if l.logFile != nil {
		return l.logFile.Close()
	}
	return nil
}

// SetMaxSize 设置最大文件大小
func (l *Logger) SetMaxSize(sizeMB int64) {
	l.mu.Lock()
	defer l.mu.Unlock()
	l.maxSize = sizeMB
}

// GetLogFiles 获取日志文件列表
func (l *Logger) GetLogFiles() ([]string, error) {
	files, err := filepath.Glob(filepath.Join(l.logDir, "app_*.log"))
	if err != nil {
		return nil, err
	}
	return files, nil
}

// CleanOldLogs 清理旧的日志文件
func (l *Logger) CleanOldLogs(daysToKeep int) error {
	files, err := l.GetLogFiles()
	if err != nil {
		return err
	}
	
	cutoffTime := time.Now().AddDate(0, 0, -daysToKeep)
	
	for _, file := range files {
		info, err := os.Stat(file)
		if err != nil {
			continue
		}
		
		if info.ModTime().Before(cutoffTime) {
			if err := os.Remove(file); err != nil {
				l.Error("Failed to remove old log file %s: %v", file, err)
			} else {
				l.Info("Removed old log file: %s", file)
			}
		}
	}
	
	return nil
}

// GetStats 获取日志统计信息
func (l *Logger) GetStats() map[string]interface{} {
	l.mu.Lock()
	defer l.mu.Unlock()
	
	stats := make(map[string]interface{})
	stats["log_dir"] = l.logDir
	stats["current_file_size_mb"] = float64(l.currentSize) / (1024 * 1024)
	stats["max_size_mb"] = l.maxSize
	
	files, err := l.GetLogFiles()
	if err == nil {
		stats["total_log_files"] = len(files)
		
		var totalSize int64
		for _, file := range files {
			if info, err := os.Stat(file); err == nil {
				totalSize += info.Size()
			}
		}
		stats["total_log_size_mb"] = float64(totalSize) / (1024 * 1024)
	}
	
	return stats
}